﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YArchitech.Revit.Electric.Common;
using HYPreviewer;
using HYRElectric.WirePlace;

namespace HYRElectric.Equipment
{
	public class WallCrossLayout : EquipmentLayout
	{
		public WallCrossLayout(UIDocument uiDoc, Document document, DbFamilyObject familyObject, FamilySymbol selectedFamilySymbol, List<BuiltInCategory> lstFilter) : base(uiDoc, document, familyObject, selectedFamilySymbol, lstFilter)
		{
		}

		private static List<Document> GetLinkDocs(Document doc)
		{
			List<Document> list = new List<Document>();
			try
			{
				foreach (RevitLinkInstance revitLinkInstance in ((IEnumerable<RevitLinkInstance>)new FilteredElementCollector(doc).OfClass(typeof(RevitLinkInstance)).Cast<RevitLinkInstance>().ToList<RevitLinkInstance>()))
				{
					list.Add(revitLinkInstance.GetLinkDocument());
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
			return list;
		}

		private void getALLDocWaLLs()
		{
			this.m_allLinkDocs = WallCrossLayout.GetLinkDocs(this.doc);
			this.m_wallList.Clear();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.doc, this.doc.ActiveView.Id);
			filteredElementCollector.WherePasses(new ElementClassFilter(typeof(Wall)));
			foreach (Element element in filteredElementCollector.ToElements())
			{
				if (element != null)
				{
					Wall item = element as Wall;
					this.m_wallList.Add(item);
				}
			}
			double elevation = this.doc.ActiveView.GenLevel.Elevation;
			foreach (Document document in this.m_allLinkDocs)
			{
				if (document != null)
				{
					FilteredElementCollector filteredElementCollector2 = new FilteredElementCollector(document);
					filteredElementCollector2.WherePasses(new ElementClassFilter(typeof(Wall)));
					foreach (Element element2 in filteredElementCollector2.ToElements())
					{
						if (element2 != null)
						{
							Wall wall = element2 as Wall;
							if (Math.Abs((document.GetElementById(wall.LevelId) as Level).Elevation - elevation) < WallCrossLayout.approximate)
							{
								this.m_wallList.Add(wall);
							}
						}
					}
				}
			}
		}

		public override bool Layout()
		{
			if (!base.Layout())
			{
				return false;
			}
			this.getALLDocWaLLs();
			this.form = new DlgLayCrossWall(this.doc);
			this.form.Show(WindowHelper.HWndRevit);
			WindowHelper.SendMessageToWndRevit();
			WireParameterInfo wireParameterInfo = new WireParameterInfo();
			for (;;)
			{
				LayWallCrossDefine laySet = this.form.m_laySet;
				wireParameterInfo.Init(this.doc);
				try
				{
					this.m_ptStart = this.docUI.Selection.PickPoint("请选取起点");
					this.m_ptEnd = this.docUI.Selection.PickPoint("请选取终点");
					if ((this.m_ptStart - this.m_ptEnd).IsZeroLength())
					{
						TaskDialog.Show("盈建科提示", "选取的两点为同一点，请选取两个不同点。");
						continue;
					}
				}
				catch (Exception)
				{
					break;
				}
				YJKCurve hycurve = new YJKCurve(Line.CreateBound(this.m_ptStart, this.m_ptEnd));
				List<XYZ> list = new List<XYZ>();
				List<double> list2 = new List<double>();
				foreach (Wall wall in this.m_wallList)
				{
					Curve curve = null;
					Curve curve2 = null;
					this.GetWallSide(ref curve, ref curve2, wall);
					if (!(curve == null) && !(curve2 == null))
					{
						XYZ xyz = hycurve.IntersectionPoint(curve);
						XYZ xyz2 = hycurve.IntersectionPoint(curve2);
						if (xyz != null && xyz2 != null)
						{
							Curve curve3 = (wall.Location as LocationCurve).Curve;
							XYZ xyz3 = (this.m_ptStart.DistanceTo(xyz) < this.m_ptStart.DistanceTo(xyz2)) ? xyz : xyz2;
							IntersectionResult intersectionResult = curve3.Project(xyz3);
							if (intersectionResult != null)
							{
								XYZ xyzpoint = intersectionResult.XYZPoint;
								XYZ xyz4 = xyz3 - xyzpoint;
								double num = XYZ.BasisY.AngleOnPlaneTo(xyz4, XYZ.BasisZ);
								XYZ item = xyz3 - 2.0 * xyz4;
								double num2 = num + Math.PI;
								if (num2 > Math.PI*2)
								{
									num2 -= Math.PI*2;
								}
								list.Add(xyz3);
								list2.Add(num);
								if (laySet.LayType == 0)
								{
									list.Add(item);
									list2.Add(num2);
								}
							}
						}
					}
				}
				for (int i = 0; i < list.Count - 1; i++)
				{
					for (int j = i + 1; j < list.Count; j++)
					{
						if (this.m_ptStart.DistanceTo(list[i]) > this.m_ptStart.DistanceTo(list[j]))
						{
							XYZ value = list[i];
							list[i] = list[j];
							list[j] = value;
							double value2 = list2[i];
							list2[i] = list2[j];
							list2[j] = value2;
						}
					}
				}
				TransactionGroup transactionGroup = new TransactionGroup(this.doc, "TransactionGroup");
				try
				{
					transactionGroup.Start();
					Transaction transaction = null;
					try
					{
						FamilyInstance startdevice = null;
						for (int k = 0; k < list.Count; k++)
						{
							XYZ xyz5 = list[k];
							double angle = list2[k] * 180.0 / Math.PI;
							transaction = new Transaction(this.doc, "LayDevice");
							transaction.Start();
							FamilyInstance familyInstance = YJKRevitTools.LayFamilySymbol(this.doc, xyz5, this.familySymbol, this.doc.ActiveView.GenLevel, angle);
							if (familyInstance == null)
							{
								throw new Exception("布置设备出错。");
							}
							base.SetParametersValue(familyInstance, this.dbFamilyObject.Size);
							Element element = familyInstance;
							string name = "标记";
							object wireName = laySet.WireName;
							LayWallCrossDefine layWallCrossDefine = laySet;
							int wireNO = layWallCrossDefine.WireNO;
							layWallCrossDefine.WireNO = wireNO + 1;
                            //ElementParameter.SetParameterValueEx(element, name, wireName + wireNO, (Autodesk.Revit.DB.ParameterType)1);
							if (!laySet.DrawWire)
							{
								transaction.Commit();
							}
							else
							{
								transaction.Commit();
                                Wire wire = NewConnectWire.CreateWire(this.doc, startdevice, familyInstance, (Autodesk.Revit.DB.Electrical.WiringType)1, null);
								if (wire != null)
								{
									this.SetWireDefineInfo(wire, wireParameterInfo);
								}
								startdevice = familyInstance;
							}
						}
					}
					catch (Exception)
					{
						if (transaction != null && transaction.GetStatus() != TransactionStatus.Committed)
						{
							transaction.RollBack();
						}
						break;
					}
					this.form.m_laySet = laySet;
					this.form.InitData();
					transactionGroup.Assimilate();
					continue;
				}
				catch (Exception)
				{
					transactionGroup.RollBack();
					continue;
				}
				break;
			}
			this.form.Close();
			return true;
		}

		private bool IsEmptyPointSet(List<List<XYZ>> pointSet)
		{
			if (pointSet == null || pointSet.Count <= 0)
			{
				return true;
			}
			foreach (List<XYZ> list in pointSet)
			{
				if (list != null && list.Count > 0)
				{
					return false;
				}
			}
			return true;
		}

		public bool GetWallSide(ref Curve wallSide1, ref Curve wallSide2, Wall wall)
		{
			Curve curve = (wall.Location as LocationCurve).Curve;
			XYZ endPoint = curve.GetEndPoint(0);
			XYZ endPoint2 = curve.GetEndPoint(1);
			double num = wall.Width / 2.0;
			if (curve as Line != null)
			{
				XYZ xyz = (endPoint - endPoint2).Normalize();
				xyz = xyz.CrossProduct(XYZ.BasisZ);
				wallSide1 = Line.CreateBound(endPoint + xyz * num, endPoint2 + xyz * num);
				wallSide2 = Line.CreateBound(endPoint - xyz * num, endPoint2 - xyz * num);
			}
			else
			{
				Arc arc = curve as Arc;
				XYZ center = arc.Center;
				XYZ xyz2 = HYPreviewer.Geometry.CalculatMidPoint(endPoint, endPoint2, center, arc.Normal);
				XYZ xyz3 = endPoint - (endPoint - center).Normalize() * num;
				XYZ xyz4 = endPoint2 - (endPoint2 - center).Normalize() * num;
				XYZ xyz5 = xyz2 - (xyz2 - center).Normalize() * num;
				XYZ xyz6 = endPoint + (endPoint - center).Normalize() * num;
				XYZ xyz7 = endPoint2 + (endPoint2 - center).Normalize() * num;
				XYZ xyz8 = xyz2 + (xyz2 - center).Normalize() * num;
				wallSide1 = Arc.Create(xyz3, xyz4, xyz5);
				wallSide2 = Arc.Create(xyz6, xyz7, xyz8);
			}
			return true;
		}

		private void SetWireDefineInfo(Wire wire, WireParameterInfo wireParInfo)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.doc);
			filteredElementCollector.OfClass(typeof(WireType));
			filteredElementCollector.ToElements();
			NewConnectWire.AddSharedParamsForWire(this.doc, wire);
		}

		private List<Wall> m_wallList = new List<Wall>();

		private List<Document> m_allLinkDocs = new List<Document>();

		private static double approximate = 0.001;

		private DlgLayCrossWall form;

		private XYZ m_ptStart;

		private XYZ m_ptEnd;
	}
}
